/************************************************************************
* Controller class, handle user interaction, update model
* Author : Shaolan
* Version : 1.0
* Website : http://shaolan.net
*/
#include "controller.hpp"

// ***********************************************************************************************************************************
// Public Constructor
Controller::Controller(){
        setModel(NULL);
		init();
}

Controller::Controller(Model * m){
        setModel(m);
		init();
}

void Controller::init(){
        input = geCreateKeys();
		repeatListener = geCreateKeys();
		timeline = geCreateTimer("timeline");
		geTimerStart(timeline);
		move = swap = down = 0;
}

int Controller::Keys[] = { GEK_UP , GEK_DOWN , GEK_RIGHT , GEK_LEFT , GEK_CROSS , GEK_CIRCLE , GEK_SQUARE , GEK_TRIANGLE , GEK_RTRIGGER , GEK_LTRIGGER };
Controller::Callback Controller::action[] = {   &Controller::upCallback , &Controller::downCallback , 
                                                                        &Controller::rightCallback , &Controller::leftCallback , 
                                                                        &Controller::crossCallback , &Controller::circleCallback , 
                                                                        &Controller::squareCallback , &Controller::triangleCallback,
																		&Controller::rCallback , &Controller::lCallback };

// ***********************************************************************************************************************************
// Public Destructor
Controller::~Controller(){
}

// ***********************************************************************************************************************************
// Getters
Model * Controller::getModel() const { return model; }

// ***********************************************************************************************************************************
// Setters
void Controller::setModel(Model * m) { model = m; }

// ***********************************************************************************************************************************
// Controller callback method

Signal Controller::crossCallback(){
	if (swap == SWAP_DELAY || repeatListener->released[GEK_CROSS]) {
		model->increaseBlock();
		swap = 0;
	}
	else if (!repeatListener->released[GEK_CROSS]) swap++;
	return SIGDONE;
}

Signal Controller::circleCallback(){
	model->increaseBlock();
    return SIGDONE;
}

Signal Controller::squareCallback(){
	model->increaseBlock();
    return SIGDONE;
}

Signal Controller::triangleCallback(){
	model->increaseBlock();
    return SIGDONE;
}

Signal Controller::upCallback(){
    return SIGDONE;
}

Signal Controller::downCallback(){
	if (down == DOWN_DELAY || repeatListener->released[GEK_DOWN]) {	
		model->move(DOWN);
		down = 0;
	}
	else if (!repeatListener->released[GEK_DOWN]) down++;
    return SIGDONE;
}

Signal Controller::leftCallback(){
	if (move == MOVE_DELAY || repeatListener->released[GEK_LEFT]) {	
		model->move(LEFT);
		move = 0;
	}
	else if (!repeatListener->released[GEK_LEFT]) move++;
    return SIGDONE;
}

Signal Controller::rightCallback(){
	if (move == MOVE_DELAY || repeatListener->released[GEK_RIGHT]) {	
		model->move(RIGHT);
		move = 0;
	}
	else if (!repeatListener->released[GEK_RIGHT]) move++;
    return SIGDONE;
}

Signal Controller::rCallback(){
	model->nextFocus();
	return SIGDONE;
}

Signal Controller::lCallback(){
	model->forwardFocus();
	return SIGDONE;
}


// ***********************************************************************************************************************************
// Update method : read user input, and check game state
bool Controller::update(){
        // Update Model 
		model->updateMapping();	
		if (model->updateFalling() == SIGLOST) return false;	
		// Check for timed clear
		if (model->getNeedClear()){
			if (!started) {
				geTimerStart(timeline);
				started = true;
			}
			model->setTimeline(timeline->seconds);
			geTimerUpdate(timeline);
			if (timeline->seconds >= model->getDelay()){
				model->updateClear();
				started = false;
			}
		} 
		else model->setTimeline(0);
        // Read key 
        geReadKeys(input);
        for (int i = 0 ; i < N_KEYS; i++){
                if (input->pressed[Keys[i]]){
                        Signal s = (this->*action[i])();
                        if (s == SIGWIN || s == SIGLOST) return false;
				}
		}
		geReadKeys(repeatListener);
        return true;
}